/* DArzt.java
 *
 * Author:	Malcolm Staudacher
 * Date:	Apr 27, 2008
 *
 */

package ocumed.domaene.benutzerverwaltung.arztverwaltung;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;

import ocumed.applikation.exceptions.WrongDayException;
import ocumed.domaene.behandlung.DWarteschlange;
import ocumed.domaene.benutzerverwaltung.DBenutzer;
import ocumed.domaene.benutzerverwaltung.DBenutzerGruppe;
import ocumed.domaene.terminverwaltung.DTermin;
import ocumed.domaene.terminverwaltung.DTerminkalender;
import ocumed.teams.IAnamnese;
import ocumed.teams.IArzt;
import ocumed.teams.IBehandlung;
import ocumed.teams.IFehlzeit;
import ocumed.teams.IOrdination;
import ocumed.teams.IPatient;
import ocumed.teams.IRezept;
import ocumed.teams.ITermin;
import ocumed.teams.IWarteposition;
import ocumed.teams.IWarteschlange;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class DArzt extends DBenutzer implements IArzt {
    private static final Log log = LogFactory.getLog(DArzt.class);

	private DTerminkalender m_kalender;
	private Vector<DFehlzeit> m_fehlzeiten;
	private Vector<DOrdinationsZeit> m_ordZeiten;
	private IWarteschlange m_warteschlange;

	private Set<IAnamnese> m_anamnesen;
	private Set<IBehandlung> m_behandlungen;
	private Set<IPatient> m_patienten;

	public DArzt(int id, DBenutzerGruppe gruppe, String username,
			String passwort, String vorname, String nachname, char status,
			Vector<DOrdinationsZeit> ordZeiten, Vector<DFehlzeit> fehlzeiten) {
		super(id, gruppe, username, passwort, vorname, nachname, status);
		m_fehlzeiten = fehlzeiten;
		m_ordZeiten = ordZeiten;
		m_kalender = new DTerminkalender(this, new Vector<DTermin>());
		m_warteschlange = new DWarteschlange(this, new TreeSet<IWarteposition>());
	}


	/**
	 * Gets appointments of the doctor on the specified day.
	 * 
	 * @param tag
	 *            The day.
	 * @return All appointments for the specified day.
	 */
	public Vector<DTermin> getTermine(Calendar tag) {
		return m_kalender.getTermine(tag);
	}


	/**
	 * 
	 * @return The doctors calendar.
	 */
	public DTerminkalender getKalender() {
		return m_kalender;
	}


	/**
	 * Sets the doctors calendar.
	 * 
	 * @param kalender
	 *            The calendar.
	 */
	public void setKalender(DTerminkalender kalender) {
		m_kalender = kalender;
		m_kalender.setArzt(this);
	}


	/**
	 * Gets 'anzahl' suggestions for appointments.
	 * 
	 * @param anzahl
	 *            The amount of suggestions to get.
	 * @param dauer
	 *            The duration of the appointments.
	 * 
	 * @return Appointment suggestions on different days.
	 */
	public ArrayList<Date> getTerminVorschlaege(Integer anzahl, int dauer) {
		ArrayList<Date> vorschlaege = m_kalender.getTerminVorschlaege(anzahl,
				dauer);

		log.debug("all absences:");
		for (DFehlzeit fz : m_fehlzeiten) {
			log.debug("ab: " + fz.getVon().getTime() + "-"
					+ fz.getBis().getTime());
		}

		return vorschlaege;
	}


	/**
	 * Gets all working times for the specified weekday in chronological order.
	 * 
	 * @param anfang
	 *            The weekday to get working times for.
	 * 
	 * @return A chronological list of the working times for the day.
	 */
	public TreeSet<DOrdinationsZeit> sortOrdZeiten(Calendar anfang) {
		TreeSet<DOrdinationsZeit> sortOrdZeiten = new TreeSet<DOrdinationsZeit>();

		for (DOrdinationsZeit coz : m_ordZeiten) {
			// get only the working times for the appropriate weekday
			log.debug("ord: " + coz.getTag() + " <--> "
					+ anfang.get(Calendar.DAY_OF_WEEK));

			if (coz.getTag() == anfang.get(Calendar.DAY_OF_WEEK)) {

				// set the proper date
				coz.getAnfang().set(anfang.get(Calendar.YEAR),
						anfang.get(Calendar.MONTH),
						anfang.get(Calendar.DAY_OF_MONTH));
				coz.getEnde().set(anfang.get(Calendar.YEAR),
						anfang.get(Calendar.MONTH),
						anfang.get(Calendar.DAY_OF_MONTH));
				// end set date

				sortOrdZeiten.add(coz);
			}

		}

		return sortOrdZeiten;
	}


	/**
	 * 
	 * @return The times of asence for this doctor.
	 */
	public Vector<DFehlzeit> getFehlzeiten() {
		return m_fehlzeiten;
	}


	/**
	 * Sets times of absence.
	 * 
	 * @param fehlzeiten
	 *            The times of absence.
	 */
	public void setFehlzeiten(Vector<DFehlzeit> fehlzeiten) {
		m_fehlzeiten = fehlzeiten;
	}
	
    /**
     * override
     * 
     * @see ocumed.teams.IBenutzer#getiWartepositions()
     */
    public synchronized IWarteschlange getiWarteschlange() {
        while (m_warteschlange == null) {
            try {
                log.debug("waiting for queue update");
                wait();
            } catch (InterruptedException e) { }
        }
        return m_warteschlange;
    }
    
    /**
     * @param warteschlange to set
     */
    public synchronized void setWarteschlange(IWarteschlange w) {
        this.m_warteschlange = w;
        notifyAll();
    }


	/**
	 * Gets all working times for this doctor.
	 * 
	 * @return All working times for this doctor.
	 */
	public Vector<DOrdinationsZeit> getOrdZeiten() {
		return m_ordZeiten;
	}


	/**
	 * Gets all times of absence for the specified weekday.
	 * 
	 * @param tag
	 *            The weekday -> must be "mo", "di", "mi", "do", "fr", "sa" or
	 *            "so".
	 * 
	 * @return All times of absence for the specified weekday.
	 * @throws WrongDayException
	 *             if the specified weekday is not in the right format.
	 */
	public Vector<DOrdinationsZeit> getOrdZeiten(String tag)
			throws WrongDayException {
		int calTag = -1;
		Vector<DOrdinationsZeit> zeiten = new Vector<DOrdinationsZeit>();

		if (tag.equals("mo")) {
			calTag = Calendar.MONDAY;
		} else if (tag.equals("di")) {
			calTag = Calendar.TUESDAY;
		} else if (tag.equals("mi")) {
			calTag = Calendar.WEDNESDAY;
		} else if (tag.equals("do")) {
			calTag = Calendar.THURSDAY;
		} else if (tag.equals("fr")) {
			calTag = Calendar.FRIDAY;
		} else if (tag.equals("sa")) {
			calTag = Calendar.SATURDAY;
		} else if (tag.equals("so")) {
			calTag = Calendar.SUNDAY;
		} else {
			throw new WrongDayException();
		}

		// choose only the times for the corresponding day
		for (DOrdinationsZeit currOrd : m_ordZeiten) {
			if (currOrd.getTag() == calTag) {
				zeiten.add(currOrd);
			}
		}

		return zeiten;
	}


	/**
	 * Sets the working times for the doctor.
	 * 
	 * @param ordZeiten
	 */
	public void setOrdZeiten(Vector<DOrdinationsZeit> ordZeiten) {
		m_ordZeiten = ordZeiten;
	}


	/**
	 * Gets this doctors patients. override
	 * 
	 * @see ocumed.teams.IBenutzer#geitPatientsForArztid()
	 */
	public Set<IPatient> getiPatientsForArztid() {
		return m_patienten;
	}


	/**
	 * override
	 * 
	 * @see ocumed.teams.IBenutzer#getiAnamneses()
	 */
	public Set<IAnamnese> getiAnamneses() {
		return m_anamnesen;
	}


	/**
	 * override
	 * 
	 * @see ocumed.teams.IBenutzer#getiBehandlungs()
	 */
	public Set<IBehandlung> getiBehandlungs() {
		return m_behandlungen;
	}


	/**
	 * override
	 * 
	 * @see ocumed.teams.IBenutzer#getiPatientsForGeandertvonid()
	 */
	public Set<IPatient> getiPatientsForGeandertvonid() {
		return null;
	}


	/**
	 * override
	 * 
	 * @see ocumed.teams.IBenutzer#getiRezepts()
	 */
	public Set<IRezept> getiRezepts() {
		// TODO Auto-generated method stub
		return null;
	}


	/**
	 * override
	 * 
	 * @see ocumed.teams.IBenutzer#getiTermins()
	 */
	public Set<ITermin> getiTermins() {
		Vector<DTermin> termine = m_kalender.getTermine();
		TreeSet<ITermin> iTermine = new TreeSet<ITermin>();

		for (DTermin t : termine) {
			iTermine.add((ITermin) t);
		}

		return iTermine;
	}


	/**
	 * override
	 * 
	 * @see ocumed.teams.IBenutzer#setBenutzerstatus(char)
	 */
	public void setBenutzerstatus(char benutzerstatus) {
		m_benutzerstatus = benutzerstatus;
	}


	/**
	 * override
	 * 
	 * @see ocumed.teams.IBenutzer#setiAnamneses(java.util.Set)
	 */
	public void setiAnamneses(Set<IAnamnese> anamneses) {
		m_anamnesen = anamneses;
	}


	/**
	 * override
	 * 
	 * @see ocumed.teams.IBenutzer#setiBehandlungs(java.util.Set)
	 */
	public void setiBehandlungs(Set<IBehandlung> behandlungs) {
		m_behandlungen = behandlungs;
	}


	/**
	 * override
	 * 
	 * @see ocumed.teams.IBenutzer#setiPatientsForArztid(java.util.Set)
	 */
	public void setiPatientsForArztid(Set<IPatient> patientsForArztid) {
		m_patienten = patientsForArztid;
	}


	/**
	 * override
	 * 
	 * @see ocumed.teams.IBenutzer#setiPatientsForGeandertvonid(java.util.Set)
	 */
	public void setiPatientsForGeandertvonid(
			Set<IPatient> patientsForGeandertvonid) {
	}


	/**
	 * override
	 * 
	 * @see ocumed.teams.IBenutzer#setiRezepts(java.util.Set)
	 */
	public void setiRezepts(Set<IRezept> rezepts) {
		// TODO Auto-generated method stub

	}


	/**
	 * override
	 * 
	 * @see ocumed.teams.IBenutzer#setiTermins(java.util.Set)
	 */
	public void setiTermins(Set<ITermin> termins) {
		// TODO Auto-generated method stub
	}


	public char getBenutzerstatus() {
		return m_benutzerstatus;
	}


	public Set<IFehlzeit> getFehlzeits() {
		TreeSet<IFehlzeit> fehlzeiten = new TreeSet<IFehlzeit>();

		for (IFehlzeit fz : m_fehlzeiten) {
			fehlzeiten.add(fz);
		}

		return fehlzeiten;
	}


	public Set<IOrdination> getOrdinations() {
		TreeSet<IOrdination> ordZeiten = new TreeSet<IOrdination>();

		for (IOrdination io : m_ordZeiten) {
			ordZeiten.add(io);
		}

		return ordZeiten;
	}

}
